以下為原始檔
https://github.com/87JoJo/02---JS-and-CSS-Clock
這次的練習,是要做一個小時鐘,而重點在於CSS的撰寫。
如上圖
首先我們要先做出圓心
,將.clock-face設為position:relative,然後在圓心設置position: absolute;,他就會往最近的relative當作定位點,注意當設置position: absolute;,位子的基準,是從該元素的「左上角」開始算起
,也就是說會如下圖這樣,因此我們光是利用left: 50%,top: 50%,並無法讓圓心置中,因為還要扣掉元素本身大小的部分(他並不是位於外框交叉,而是靠外框左上),所以還要利用transform: translate(X,Y)方法
,參數分別代表位移X距離、位移Y距離,如使用%,是以元素本身大小作為計算基準,如果只寫一個參數,省略的第2個參數會視為0
。
而這個為偽元素
,我們利用它來做圓心及針的部分,他可以有 CSS 屬性,可以影響畫面,但是它不是實際存在的 HTML 結構
,所以我們在console只會看到::after的元素,而我們也須加上content: '',display: block
讓其佔有實際的位置,而::after是在元素的之後插入其他內容,::before反之。
.clock-face::after {
position: absolute;
content: '';
width: 20px;
height: 20px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: white;
border-radius: 50%;
display: block;
}
而再來就按照設置圓心的方法,分別設置時針、分針、秒針。
在js部分,先利用選擇器獲取時針、分針、秒針。
const hour = document.querySelector('.hour-hand'),
min = document.querySelector('.min-hand'),
second = document.querySelector('.second-hand');
接著,我們設一個setClock函數來做時間及針的擺動計算操作。
先利用new Date();
獲取現在時間,在利用當前時間,分別獲取時getHours()
、分getMinutes()
、秒getSeconds()
,再來就要設置我們擺動的角度,讓他在對應時間移動到相對的位置,由於圓圈是360度,基本上,除以60秒,1秒移動6度,除以60分,1分移動6度,除以12小時,1時移動30度,在乘上當前時分秒,即可得到對應角度,
但是,我們還需要考慮到分、時針不可能永遠在整點,一定有多餘的時間
,所以要加上多餘的時間,對於時針,一分會移動1/2度,對於分針一秒會移動1/10度。
我們利用rotate屬性來處理針的擺動,利用style,直接在時針、分針、秒針上添加transform:rotate
,利用模板字符串來將我們設置好的屬性值寫進去即可。
function setClock() {
// 獲取現在時間
const time = new Date();
// 獲取時,分,秒
const nowSec = time.getSeconds(),
nowMin = time.getMinutes(),
nowHour = time.getHours();
// 設置移動角度
const secDeg = (360 / 60) * nowSec, // 360度/60秒
// 後面數值為多餘秒數會移動的角度 1秒移動 1/10度
minDeg = (360 / 60) * nowMin + (6 / 60) * nowSec,
// 後面數值為多餘分鐘會移動的角度,1分移動 1/2度
hourDeg = (360 / 12) * nowHour + (30 / 60) * nowMin;
// 利用style直接改變定義transform並添加rotate讓針翻轉
hour.style.transform = `rotate(${hourDeg}deg)`;
min.style.transform = `rotate(${minDeg}deg)`;
second.style.transform = `rotate(${secDeg}deg)`;
}
再來在最外面呼叫setClock,初始化畫面,最後,設定計時器,而設定計時器有三種方法:如下
setClock();
// 三種計時方法
// 間隔1秒,持續觸發
setInterval(setClock, 1000);
// 等一秒後,觸發一次(用來設定延遲)
setTimeout(timeHandler, 1000);
在function裡面添加timeHandler
function timeHandler() {
setClock();
// 因為只會執行一次,所以在函數裡在執行一次
setTimeout(timeHandler, 1000);
}
處理畫面更新(與畫面更新頻率有關)的setTimeout,當在處理複雜動畫就用requestAnimationFrame。
window.requestAnimationFrame(animationHandler, 1000);
function animationHandler() {
setClock();
// 因為只會執行一次,所以在函數裡在執行一次
window.requestAnimationFrame(animationHandler, 1000);
}